#include <string.h>
#include "board.h"
#include "lcd_dev.h"
#include "esp_lvgl_port.h"
#include "esp_lcd_touch_ft5x06.h"

#define TAG "LVGL_MANAGER"

struct lvgl_manager_t {
    lv_disp_t *disp;
    lv_indev_t *indev;
    esp_lcd_touch_handle_t ret_touch;
};

struct lvgl_manager_t lvgl_manager;

static esp_err_t lvgl_manager_touch_new(esp_lcd_touch_handle_t *ret_touch)
{
    /* Initialize touch */
    esp_lcd_touch_config_t tp_cfg = {
        .x_max = BSP_LCD_H_RES,
        .y_max = BSP_LCD_W_RES,
        .rst_gpio_num = GPIO_NUM_NC, // Shared with LCD reset
        .int_gpio_num = GPIO_NUM_NC, 
        .levels = {
            .reset = 0,
            .interrupt = 0,
        },
        .flags = {
            .swap_xy = 1,
            .mirror_x = 1,
            .mirror_y = 0,
        },
    };
    esp_lcd_panel_io_handle_t tp_io_handle = NULL;
    esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();

    ESP_RETURN_ON_ERROR(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)BSP_I2C_NUM, &tp_io_config, &tp_io_handle), TAG, "");
    ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, ret_touch));

    return ESP_OK;
}

static lv_disp_t *lvgl_manager_register_display(void)
{
    struct device* lcd_dev = device_get_binding("st7789");

    struct st7789_data *lcd_data = (struct st7789_data *)lcd_dev->driver_data;
    const struct st7789_config *lcd_config = (struct st7789_config *)lcd_dev->config->config_info;

    ESP_LOGD(TAG, "Add LCD screen");
    const lvgl_port_display_cfg_t disp_cfg = {
        .io_handle = lcd_data->io_handle,
        .panel_handle = lcd_data->panel_handle,
        .buffer_size = lcd_config->width * BSP_LCD_DRAM_BUF_HEIGHT,   // LVGL缓存大小 
        .double_buffer = true, // 是否开启双缓存
        .hres = lcd_config->width, // 液晶屏的宽
        .vres = lcd_config->height, // 液晶屏的高
        .monochrome = false,  // 是否单色显示器
        /* Rotation的值必须和液晶屏初始化里面设置的 翻转 和 镜像 一样 */
        .rotation = {
            .swap_xy = true,  // 是否翻转
            .mirror_x = true, // x方向是否镜像
            .mirror_y = false, // y方向是否镜像
        },
        .flags = {
            .buff_dma = false,  // 是否使用DMA 注意：dma与spiram不能同时为true
            .buff_spiram = true, // 是否使用PSRAM 注意：dma与spiram不能同时为true
        }
    };

    return lvgl_port_add_disp(&disp_cfg);
}

static lv_indev_t *lvgl_manager_register_input(lv_disp_t *disp)
{
    /* 初始化触摸屏 */
    ESP_ERROR_CHECK(lvgl_manager_touch_new(&lvgl_manager.ret_touch));
    assert(lvgl_manager.ret_touch);

    /* 添加LVGL接口 */
    const lvgl_port_touch_cfg_t touch_cfg = {
        .disp = disp,
        .handle = lvgl_manager.ret_touch,
    };

    return lvgl_port_add_touch(&touch_cfg);
}

void lvgl_manager_init(void)
{
    memset(&lvgl_manager, 0, sizeof(lvgl_manager));

    lvgl_port_cfg_t lvgl_cfg = ESP_LVGL_PORT_INIT_CONFIG();
    lvgl_port_init(&lvgl_cfg);

    lvgl_manager.disp = lvgl_manager_register_display();
    lvgl_manager.indev = lvgl_manager_register_input(lvgl_manager.disp);
}